/**
 *    Copyright (C) 2008, 2009  Victor Smirnov <aist11@gmail.com>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *    See LICENSE.exceptions in the root folder of this project for possible
 *    exceptions
 *
 */

#ifndef _CUBEFS_CORE_CONTAINER_ITERATOR_HPP
#define	_CUBEFS_CORE_CONTAINER_ITERATOR_HPP

#include <cubefs/api/types.hpp>
#include <cubefs/core/tools/types/typelist.hpp>

#include <cubefs/core/container/names.hpp>
#include <cubefs/core/container/container/container.hpp>

namespace cubefs    {
namespace ctr       {

using cubefs::TypeList;

template <typename Profile_, typename MyType, typename ModelType>
class IteratorBase: public ModelType::Types::IteratorInterface {
public:

	typedef Profile_															Profile;
    typedef ModelType                                                           Model;
    typedef typename Model::PageMgr                                             PageMgr;
    typedef typename PageMgr::Page::ID                                          PageId;

    enum {_EOF = 1, BOF = 2, EMPTY = 4, START = 8};
    
private:
    MyType& me_;
    int     state_;
    
public:
    IteratorBase(MyType &me): me_(me), state_(0) {}

    MyType &me() {
        return me_;
    }

    const MyType &me() const {
        return me_;
    }

    void setup(const MyType &other) {
        state()   = other.state();
    }

    Int &state() {
        return state_;
    }

    void set_state(Int state) {
        state_ = state;
    }

    void reset_state() {
        state_ = 0;
    }

    const Int& state() const {
        return state_;
    }

    bool IsEof() const {
        return (state() & EOF) != 0;
    }

    void SetStateBit(int flag, bool bit) {
        if (bit) {
            state_ |= flag;
        }
        else {
            state_ &= ~flag;
        }
    }

    void SetEof(bool eof) {
        SetStateBit(_EOF, eof);
    }

    bool IsBof() const {
        return (state_ & BOF) != 0;
    }

    void SetBof(bool bof) {
        SetStateBit(BOF, bof);
    }

    bool IsEmpty() const {
        return (state_ & EMPTY) != 0;
    }

    bool IsNotEmpty() const {
        return (state_ & EMPTY) == 0;
    }

    void SetEmpty(bool empty) {
        SetStateBit(EMPTY, empty);
    }

    bool IsStart() const {
        return (state_ & START) != 0;
    }

    void SetStart(bool start) {
        SetStateBit(START, start);
    }

    bool is_log(Int level)
    {
        return level >= logger().GetLogLevel();
    }

    cubefs::api::Logger& logger() {
        return me_.model().logger();
    }

    const std::string& type_name() const {
        return me_.model().type_name();
    }
};

template <
        typename Name,
        typename MyType,
        typename Base
>
class IteratorPart;

template <typename Model> class IteratorFactoryName{};

template<
        typename Profile,
        typename ModelType,
        typename MyType
>
class Iterator: public TypeAwareBuilder <
        typename ModelType::IteratorPartsList,
        IteratorPart,
        MyType,
        typename ModelType::Types::template IteratorBaseFactory<
			MyType,
			ModelType
		>::Type
>
{
    typedef TypeAwareBuilder<
        typename ModelType::IteratorPartsList,
        IteratorPart,
        MyType,
        typename ModelType::Types::template IteratorBaseFactory<
			MyType,
			ModelType
		>::Type
    >                                                                           Base;
public:

    typedef typename ContainerTypesLocator<Profile>::PageManagerType            PageMgr;
    typedef typename PageMgr::Transaction                                       Txn;
    typedef ModelType                                                           Model;

protected:
    ModelType&      model_;

public:
    
    Iterator(MyType &me, ModelType &model): Base(me), model_(model) {}

    ModelType& model() {
        return model_;
    }

    const ModelType& model() const {
        return model_;
    }

    void setup(const MyType &other) {
        Base::setup(other);
    }
};

}
}

#endif
